//+FHEADER /////////////////////////////////////////////////////////////////////////////
// FILE NAME :  code_cntrl.v
// DEPARTMENT:  N/A
// AUTHOR:DingXU
// AUTHOR'S EMAIL : N/A
// --------------------------------------------------------------------------
// RELEASE HISTORY
// VERSION DATE AUTHORDESCRIPTION
// 1.0 2020-05-17  DingXU initial version  
// Added comments in header:
//---------------------------------------------------------------------------
// KEYWORDS :  state, code
//--------------------------------------------------------------------------
// PURPOSE:   Coding state machine
// --------------------------------------------------------------------------
// PARAM NAME RANGE  N/A
// -----------------------------------------------------------------------
// REUSE ISSUES
// Reset Strategy : Asynchronous, active low system level reset : 
// Clock Domains : i_clk 
// Critical TiminG: N/A
// Instantiations : no
// Synthesizable : Yes 
//-FHEADER //////////////////////////////////////////////////////////////////////
module code_cntrl(
                  i_clk               ,//LDPC calculation clock
                  i_rst_n             ,//LDPC reset signal
                  i_empty             ,//Input FIFO empty signal
                  i_full              ,//Input FIFO full signal	 
                  i_code_en           ,//LDPC encoding enable signal     
                  o_code_en           ,//LDPC encoding submodule enable signal
                  o_read              ,//Input FIFO read signal
                  o_cnt               ,//Stage counter
                  o_code_finish        //Encoding end signal
                    );
                    
///////////////////////////////////////
//declaration of input & output
///////////////////////////////////////
input             i_clk               ;
input             i_rst_n             ;
input             i_code_en           ;
input             i_empty             ;
input             i_full              ;
output            o_code_en           ;
output            o_read              ;
output   [6:0]    o_cnt               ;
output            o_code_finish       ;

///////////////////////////////////////
//declaration of registers & wires
///////////////////////////////////////
reg      [4:0]    state               ;
reg      [4:0]    n_state             ; 
reg               o_code_finish       ;
reg      [6:0]    o_cnt               ;
reg               o_code_en           ;
reg               o_read              ;

parameter CNT_READMAX    = 7'd86      ;
parameter CNT_CODEMAX    = 7'd102     ;

// STATE 
parameter IDLE        = 5'b00001      ;
parameter READING     = 5'b00010      ;
parameter CODING      = 5'b00100      ;
parameter WAITTING_W  = 5'b01000      ;
parameter WAITTING_R  = 5'b10000      ;

///////////////////////////////////////
//            program 
///////////////////////////////////////
always@(posedge i_clk or negedge i_rst_n)
begin
    if(i_rst_n == 1'b0)  begin
        state     <= IDLE             ;
    end else begin
        state     <= n_state          ;
    end
end

///////////////////////////////////////
//There are five states for encoding: 
//IDLE; READING;CODING;
//waiting for writing; waiting for reading.
//Rely on external coded signals, 
//asynchronous fifo empty and full signals, 
//external wait for signal conversion, 
//where empty and full signals need to respond in time.
///////////////////////////////////////    
always@(state or i_code_en or o_cnt or i_empty or i_full)
begin 
    case(state)
        IDLE:begin if((i_empty == 1'b0)&&(i_code_en == 1'b1)) begin 
                       n_state   <= READING      ;
                   end else begin
                       n_state   <= IDLE         ;
              end end 

        READING:begin if(o_cnt == CNT_READMAX) begin
                       n_state   <= CODING       ;
               end else if((i_empty == 1'b1)&&(o_cnt <= CNT_READMAX - 1)) begin
                       n_state   <= WAITTING_W   ;       
               end else if(i_full == 1'b1) begin
                       n_state   <= WAITTING_R   ;       
               end else  begin 					
                       n_state   <= READING      ;
               end end                             
				  
        CODING:begin if(o_cnt == CNT_CODEMAX) begin
                       n_state   <= IDLE         ;              
               end else  begin 					
                       n_state   <= CODING       ;
               end end
					
        WAITTING_W:begin if(i_empty == 1'b0) begin
                       n_state   <= READING      ;
               end
               else begin               
                       n_state   <= WAITTING_W   ;
               end end
					
        WAITTING_R:begin if(i_full == 1'b0) begin
                       n_state   <= READING      ;
               end
               else begin               
                       n_state   <= WAITTING_R   ;
               end end 
               
        default:       n_state   <= IDLE         ;
    endcase
end

always@(state)
begin
    case(state)
        IDLE:begin  
                 o_read         <= 1'b0          ;    
                 o_code_en      <= 1'b0          ;
                 o_code_finish  <= 1'b1          ;
             end
        READING:begin
                 o_read         <= 1'b1          ;
                 o_code_en      <= 1'b1          ;
                 o_code_finish  <= 1'b0          ;
             end             
        CODING:begin 
                 o_read         <= 1'b0          ;
                 o_code_en      <= 1'b1          ;
                 o_code_finish  <= 1'b0          ;
             end  
        WAITTING_W:begin
                 o_read         <= 1'b0          ;
                 o_code_en      <= 1'b0          ;
                 o_code_finish  <= 1'b0          ;
             end
        WAITTING_R:begin
                 o_read         <= 1'b1          ;
                 o_code_en      <= 1'b1          ;
                 o_code_finish  <= 1'b0          ;                        
             end                      
        default:begin
                 o_read         <= 1'b0          ;
                 o_code_en      <= 1'b0          ;
                 o_code_finish  <= 1'b0          ;
             end  
     endcase 
end 

///////////////////////////////////////
//           Stage counter
///////////////////////////////////////
always@(posedge i_clk or negedge i_rst_n)
begin
    if(i_rst_n == 1'b0)  
        o_cnt <= 7'd0                            ;		  
    else if(state == IDLE)
        o_cnt <= 7'd0                            ;
    else if((state == CODING)||(state == READING)&&(i_empty == 1'b0))
        o_cnt <= o_cnt + 7'd1                    ;
    else if(state == WAITTING_W)
	      o_cnt <= o_cnt                           ;
    else	  
        o_cnt <= o_cnt                           ;
end  
       
endmodule
		  
		  
		  
		  
		  
		  
		  
		  
		  